/**
 * <p>Title: GuiCtrl</p>
 *
 * <p>Copyright: Copyright (c) 2007</p>
 *
 * <p>Company: Soluciones Info Moviles</p>
 *
 * @author Lobsang Alvites Szaler
 * @author Rodolfo Burlando M.
 * @version 1.0
 */

package sim.framework.gui;

import java.util.*;
import javax.microedition.lcdui.*;

import sim.framework.*;
import sim.framework.font.*;
import sim.framework.gui.*;
import sim.utils.*;
import java.lang.*;

public abstract class GuiCtrl {

    // Tipos de controles.
    public static final int UNKNOW = 0;
    public static final int SPACE = 1;
    public static final int LIST = 2;
    public static final int MULTIOPT = 3;
    public static final int SOFTMENU = 4;
    public static final int BANNER = 5;
    public static final int PROMPT = 6;
    public static final int TITLE = 7;
    public static final int LABEL = 8;
    public static final int TEXT = 9;
    public static final int NUMERIC = 10;
    public static final int NUMSP = 11;
    public static final int DECIMAL = 12;
    public static final int PERCENT = 13;
    public static final int IPADDR = 14;
    public static final int REAL = 15;
    public static final int TIME = 16;
    public static final int DATE = 17;
    public static final int DAY = 18;
    public static final int COMBO = 19;
    public static final int CHECKBOX = 20;
    public static final int RADIOGROUP = 21;

    // Mensajes soportados por los controles.
    public static final int MSG_GETTEXT       = Gui.MSG_USER + 1;
    public static final int MSG_SETTEXT       = Gui.MSG_USER + 2;
    public static final int MSG_GETITEMTEXT   = Gui.MSG_USER + 3;
    public static final int MSG_SETITEMTEXT   = Gui.MSG_USER + 4;
    public static final int MSG_GETCOUNT      = Gui.MSG_USER + 5;
    public static final int MSG_GETCURSORPOS  = Gui.MSG_USER + 6;
    public static final int MSG_SETCURSORPOS  = Gui.MSG_USER + 7;
    public static final int MSG_GETITEMID     = Gui.MSG_USER + 8;
    public static final int MSG_GETVALUE      = Gui.MSG_USER + 9;
    public static final int MSG_SETVALUE      = Gui.MSG_USER + 10;
    public static final int MSG_SELECTITEM    = Gui.MSG_USER + 11;
    public static final int MSG_GETINITTEXT   = Gui.MSG_USER + 12;
    public static final int MSG_GETNEXTTEXT   = Gui.MSG_USER + 13;
    public static final int MSG_GETINITID     = Gui.MSG_USER + 14;
    public static final int MSG_GETNEXTID     = Gui.MSG_USER + 15;
    public static final int MSG_ADDTEXT       = Gui.MSG_USER + 16;
    public static final int MSG_GETITEMVALUE  = Gui.MSG_USER + 17;
    public static final int MSG_SETITEMVALUE  = Gui.MSG_USER + 18;
    public static final int MSG_ADDIMAGE      = Gui.MSG_USER + 19; // NO USAR TODAVIA
    public static final int MSG_REMOVEITEM    = Gui.MSG_USER + 20;
    public static final int MSG_ADDITEM       = Gui.MSG_USER + 21;
    public static final int MSG_GETPROPERTIES = Gui.MSG_USER + 22;
    public static final int MSG_SETPROPERTIES = Gui.MSG_USER + 23;

    // Soporte a creación por scripts.
    public static final byte[] LIST_NAME = "list".getBytes();
    public static final byte[] BANNER_NAME = "banner".getBytes();
    public static final byte[] MULTIOPT_NAME = "multiopt".getBytes();
    public static final byte[] SOFTMENU_NAME = "softmenu".getBytes();
    public static final byte[] PROMPT_NAME = "prompt".getBytes();
    public static final byte[] TITLE_NAME = "title".getBytes();
    public static final byte[] LABEL_NAME = "label".getBytes();
    public static final byte[] TEXT_NAME = "text".getBytes();
    public static final byte[] NUMERIC_NAME = "numeric".getBytes();
    public static final byte[] NUMSP_NAME = "numsp".getBytes();
    public static final byte[] DECIMAL_NAME = "decimal".getBytes();
    public static final byte[] PERCENT_NAME = "percent".getBytes();
    public static final byte[] IPADDR_NAME = "ipaddr".getBytes();
    public static final byte[] REAL_NAME = "real".getBytes();
    public static final byte[] TIME_NAME = "time".getBytes();
    public static final byte[] DATE_NAME = "date".getBytes();
    public static final byte[] DAY_NAME = "day".getBytes();
    public static final byte[] COMBO_NAME = "combo".getBytes();

    public static final int CTRL_VMARGIN = 1;
    public static final int CTRL_HMARGIN = 1;
    public static final int VIEW_VMARGIN = 1;
    public static final int VIEW_HMARGIN = 1;

    protected static final int MAX_SIZE_AVAILABLE = -1;

    // La siguiente constante debe estar en GuiCtrlItem
    public static final int INVALID_ITEM_ID = 0xFFFFFFFF;

    private int id; // Nomenclatura incorrecta (identificador unico del control)
    protected FontSingle font; // Nomenclatura incorrecta (Tipo de letra, Referencia?)
    protected int m_Properties = 0;

    protected int x; // Nomemclatura incorrecta
    protected int y; // Nomemclatura incorrecta
    protected int dx; // Nomemclatura incorrecta
    protected int dy; // Nomemclatura incorrecta
    protected int width; // Nomemclatura incorrecta (Cual se usa?). En el futuro lo usaremos para Algoritmo AutoResize
    protected int height; // Nomemclatura incorrecta (Cual se usa?). En el futuro lo usaremos para Algoritmo AutoResize

    public boolean bFocus; // Nomemclatura incorrecta ([T/F] Control owns the focus)
    public boolean bActive; // Nomenclatura incorrecta (control activo o no)
    protected boolean m_bRepaint;   // [T/F] Controls must repaint itself

    // Lo siguiente son variables y no constantes (CADA CONTROL ESTABLECE SU VALOR).
    public static final int COLOR_FOCUS_BOX_LINE = 0x000000;    // 0,0,0 (ej. box lines)
    public static final int COLOR_FOCUS_ITEM = 0xC8E4F0;        // 200,228,240 (ej. ctrlList item)
    public static final int COLOR_FOCUS_BG = 0xEEEEFF;          // 238,238,255 (ej. ctrlPrompt bg)
    public static final int COLOR_FOCUS_BAR_BG = 0xB4C8F0;      // 180,200,240 (scrollbar bg)
    public static final int COLOR_FOCUS_BAR_HANDLER = 0x788CDC; // 120,140,220 (scrollbar bg)
    
    // no focus
    public static final int COLOR_BOX_LINE = 0xA2A2C6;      // 162,162,198 (ej. box lines)
    public static final int COLOR_ITEM = 0xE8F0F8;         // (ej. ctrlList item)    
    public static final int COLOR_BG = 0xFFFFFF;            // (ej. ctrlPrompt bg)
    public static final int COLOR_BAR_BG = 0xD7E3F9;        // (scrollbar bg)
    public static final int COLOR_BAR_HANDLER = 0xBAC4EE;   // 120,140,220 (scrollbar bg)
    
    public static final int COLORFOCUS2 = 0x8C8C8C;     // Focus Color when a Controller is active
    public static final int COLORSHADOW = 0xBED2C8;     // Color de sombra

    protected int minHeight() {
	if (font != null) {
	    return (font.getHeight() + 2*CTRL_VMARGIN + 2*VIEW_VMARGIN);
	}
	return MAX_SIZE_AVAILABLE;
    }

    protected int minWidth() {
	return MAX_SIZE_AVAILABLE;
    }

    protected final void setFont( final FontSingle fnt ){
        this.font = fnt;
    }
    
    /** Creates a new instance of GuiCtrl */
    public GuiCtrl(int id, final FontSingle font) {
        setID(id);
        setFont(font);
    }
    
    /**
     * Definimos in ID (identificador) para el control.
     * @param int id    Identificador del control
     */
    protected final void setID(int id) {
        this.id = id;
    }
    
    /**
     * Entrega el id asignado al control.
     * @return int id   identificador del control.
     */
    protected final int getID() {
        return id;
    }
    
    /**
     *  Sets the Focus state for this Control
     *  @param  state   True if it has the focus, False if not.
     */
    protected void setFocus(boolean state) {
        bFocus = state;
        repaint();
    }
    
    /**
     *  Gets the Focus state for this Control.
     *  @return Focus state of this control. True or False.
     */
    public final boolean focus() {
        return bFocus;
    }

    public final void repaint() {
        m_bRepaint = true;
    }
    
    /**
     *  Gets the ID Type for this Control.
     */
    public int getType() {
	return GuiCtrl.UNKNOW;
    }
    
    /**
     * Definimos el ancho del control
     *
     * @param int ancho Definimos el ancho del control.
     */
    public void setWidth( final int ancho ) {
        this.dx = ancho;
    }
    
    /**
     * Consultamos por el ancho del control
     *
     * @return int dx   Ancho del control.
     */
    public final int getWidth(){
        return dx;
    }
    
    /**
     * Definimos el alto del control
     *
     * @param int altura. Definimos altura del componente visual en pantalla.
     */
    public void setHeight( final int altura ) {
        this.dy = altura;
    }
    
    /**
     * Consultamos por el alto del control
     *
     * @return int dy   Altura del control.
     */
    public final int getHeight() {
        return dy;
    }

    /**
     * Consultamos por el alto del control
     *
     * @return int dy   Altura del control.
     */
    protected final int getY() {
        return y;
    }
    
    /**
     * Definimos si esta procesado por el GUI o pendiente
     *
     * @param process boolean
     */
    protected final void setProcess( final boolean process ) {
        this.process = process;
    }

    /**
     * Preguntamos si esta procesado o pendiente para el GUI
     * Hace referencia al proceso de ordenamiento de controles que se hace desde el GUI
     *
     * @return boolean
     */
    protected final boolean getProcess() {
        return process;
    }

    /**
     * Definimos el valor de la propiedad texto del control.
     *
     * @param String    texto
     */
    public int setText( final String str ) {
        repaint();
        texto = str;
//        if( texto != null ) {
//            return texto.length();
//        }
	return 0;
    }
    
    /**
     * Nos devuelve el valor de la propiedad texto del control
     * @return String   texto
     */
    public String getText() {
        return texto;
    }
    
    // Metodos Abstractos a implementar en clases que hereden a GuiCtrl
    protected abstract void paint(Graphics g);


    /** 
     * Envio de mensajes.
     *
     * Las futuras versiones de controles que deriven de GuiCtrl. deben
     * mapear el mensaje a GuiCtrl.
     *
     * @param msgID 
     * @param param1 
     * @param param2 
     * 
     * @return El valor devuelto depende del tipo de control.
     */
    protected int sendMessage(int msgID, int param1, Object param2) {
	return 0;
    }

    /**
     * Despacho de eventos enviados por el Gui.
     *
     * @param Msg msg   mensaje con detalles del evento
     * @return boolean
     */
    protected boolean dispatchEvent(Msg msg) {
	return false;
    }

    /**
     * Returns the focusable attribute for this Control.
     *
     * @return True if Control is focusable or False if not
     */
    protected abstract boolean focusable();
    
    /*
     *  Sets the activation state of the control.
     *  @param  state   True to activate the Control, or False to deactivate it
     */
    public final void setActive( boolean state ) {
        this.bActive = state;
        repaint();
    }
    
    /*
     *  Gets the activation state of the control.
     *  @return  True if Control is active or False if not
     */
    public final boolean getActive() {
        return bActive;
    }
        
    /** 
     * Devuelve el tipo de control dado su nombre.
     * 
     * @param line Arreglo de bytes que contiene el nombre de un control.
     * @param start Primer byte válido del arreglo.
     * @param length Longitud, en bytes, válidos del arreglo.
     * 
     * @return Devuelve un indentificador para el tipo de control. Si el nombre
     *         no corresponde a un control, la función devuelve GuiCtrl.UNKNOW.
     */
    public static int str2type(final byte[] line, int start, int length) {
	int l;
	l = Math.min(length, 4);
	if (l > 0) {
	    if(Utils.memnicmp(line, start, length, LIST_NAME, l) == 0)
		return LIST;
	    else if(Utils.memnicmp(line, start, length, MULTIOPT_NAME, l) == 0)
		return MULTIOPT;
	    else if(Utils.memnicmp(line, start, length, TEXT_NAME, l) == 0)
		return TEXT;
	    else if(Utils.memnicmp(line, start, length, NUMERIC_NAME, l) == 0)
		return NUMERIC;
	    else if(Utils.memnicmp(line, start, length, NUMSP_NAME, l) == 0)
		return NUMSP;
	    else if(Utils.memnicmp(line, start, length, DECIMAL_NAME, l) == 0)
		return DECIMAL;
	    else if(Utils.memnicmp(line, start, length, PERCENT_NAME, l) == 0)
		return PERCENT;
	    else if(Utils.memnicmp(line, start, length, IPADDR_NAME, l) == 0)
		return IPADDR;
	    else if(Utils.memnicmp(line, start, length, REAL_NAME, l) == 0)
		return REAL;
	    else if(Utils.memnicmp(line, start, length, TIME_NAME, l) == 0)
		return TIME;
	    else if(Utils.memnicmp(line, start, length, DATE_NAME, l) == 0)
		return DATE;
	    else if(Utils.memnicmp(line, start, length, DAY_NAME, l) == 0)
		return DAY;
	    else if(Utils.memnicmp(line, start, length, COMBO_NAME, l) == 0)
		return COMBO;
	}
	return UNKNOW;
    }

    public void setProperties(int flags) {
	m_Properties = flags;
    }

    public int getProperties() {
	return m_Properties;
    }

    protected int renderer() {
	return 0;
    }


    // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    
    // El siguiente código debe desaparecer.
    //
    // - No son requeridos para resolver el problema del GUI.
    // - Algunos tienen nombres no apropiados.
    //

    //protected   Gui     gui;	// No tiene sentido.
    private     String  title;	// Esto se debe eliminar
    protected   String  texto;	// Esto se debe eliminar
    protected   StringBuffer    m_StrBuf = new StringBuffer(); // Esto se debe eliminar
    protected int scrWidth;    // ????
    protected int scrHeight;   // ????


    private boolean process;            // No tiene sentido, se debe eliminar (bandera para saber si esta procesado por el GUI )

    protected void init() {
    }
    protected void run() {

    }

//     public final void setGui( final Gui gui ) {
//         this.gui = gui;
//     }
}
